package wordit.impl.letterCells;

import java.util.Collection;
import java.util.LinkedList;
import java.util.Vector;

import wordit.Letter;
import wordit.LetterSequence;
import wordit.ea.AbstractGenome;



/**
 * Version 1 of a genome (solution) representation:
 * A vector of a letter-cell couples - each letter
 * has a fixed position on the board.
 */
public class LetterCellGenome extends AbstractGenome {

	private Vector<LetterCell> letterCells;
	private int numOfRowsOnBoard;
	private int numOfColumnsOnBoard;	
	
	public LetterCellGenome (int numOfRowsOnBoard, int numOfColumnsOnBoard) {
		this.numOfRowsOnBoard = numOfRowsOnBoard;
		this.numOfColumnsOnBoard = numOfColumnsOnBoard;
		this.letterCells = new Vector<LetterCell> ();
	}
	
	public void addLetterCell(LetterCell letterCell) {
		this.letterCells.add(letterCell);
	}

	//If there is a letter on location - returns it, else returns NULL 
	public Letter getLetterAt(int location) {	
		Letter l = null;
		int currentLetterIndex = 0;
		while (currentLetterIndex < letterCells.size() && l == null) {
			if (letterCells.elementAt(currentLetterIndex).getCell() == location) {
				l = letterCells.elementAt(currentLetterIndex).getLetter();
			} else {
				currentLetterIndex++;
			}
		}
		return l;
	}
	
	public void setLetterCellAt (int index, LetterCell newLetterCell ) {
		if (index < letterCells.size()) {
			letterCells.setElementAt(newLetterCell, index);
		}
	}
	
	public LetterCell getLetterCellAt(int index) {
		if (index < letterCells.size()) {
			return letterCells.elementAt(index);			
		} else {
			return null;
		}
	}
	
	public int getNumOfLetterCells () {
		return letterCells.size();
	}
	
	public Collection<LetterSequence> getSequences() {
		Collection<LetterSequence> sequences = new LinkedList<LetterSequence>();

		for (int row = 0; row < numOfRowsOnBoard; ++row)
			sequences.addAll(getSequencesInRow(row));

		for (int column = 0; column < numOfColumnsOnBoard; ++column) {
			for (LetterSequence s : getSequencesInColumn(column)) {
				// 1-letter sequences are ignored here, since they were already
				// added as row sequences
				if (s.getLength() > 1)
					sequences.add(s);
			}
		}

		return sequences;
	}
	
	public String toString() {
		return "(LetterCellGenome," + getFitness() + "," + getSequences() + ")";
		
		/*
		
		String retValue = "";
		for (int i=0; i<letterCells.size(); i++) {
			if (i == 10) {
				retValue += "\n\t";
			}
			retValue += letterCells.get(i).getLetter() + " - "  + letterCells.get(i).getCell() + " ";
		}
		return retValue;
		
		*/
	}
	
	private Collection<LetterSequence> getSequencesInRow(int row) {
		Collection<LetterSequence> sequences = new LinkedList<LetterSequence>();

		LetterSequence seq = null;
		for (int column = 0; column < numOfColumnsOnBoard; ++column) {
			if (getLetterAt(row * numOfColumnsOnBoard + column) == null) {
				// nothing at this spot

				// if its because a sequence ended, keep it
				if (seq != null) {
					sequences.add(seq);
					seq = null;
				}
			} else {
				// got a letter

				// if first in sequence - prepare sequence
				if (seq == null) {
					seq = new LetterSequence();
				}

				// anyway, append it
				seq.addLetter(getLetterAt(row * numOfColumnsOnBoard + column));
			}
		}

		// any leftovers? keep them
		if (seq != null) {
			sequences.add(seq);
			seq = null;
		}

		return sequences;
	}
	
	private Collection<LetterSequence> getSequencesInColumn(int column) {
		Collection<LetterSequence> sequences = new LinkedList<LetterSequence>();

		LetterSequence seq = null;
		for (int row = 0; row < numOfRowsOnBoard; ++row) {
			if (getLetterAt(row * numOfColumnsOnBoard + column) == null) {
				// nothing at this spot

				// if its because a sequence ended, keep it
				if (seq != null) {
					sequences.add(seq);
					seq = null;
				}
			} else {
				// got a letter

				// if first in sequence - prepare sequence
				if (seq == null) {
					seq = new LetterSequence();
				}

				// anyway, append it
				seq.addLetter(getLetterAt(row * numOfColumnsOnBoard + column));
			}
		}

		// any leftovers? keep them
		if (seq != null) {
			sequences.add(seq);
			seq = null;
		}

		return sequences;
	}
	
	

}
